using System;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;

namespace Comteck.Ktt.Services.Plugs.EMS {
  internal class SM4Crypto {
    public static string GenerateSm4Key() {
      return Guid.NewGuid().ToString().Replace("-", string.Empty)
        .Substring(0, 16);
    }

    public static string Sm4Encrypt(string plaintext, string sm4Key) {
      byte[] bytes = Encoding.UTF8.GetBytes(plaintext);
      byte[] bytes2 = Encoding.UTF8.GetBytes(sm4Key);
      return Sm4Encrypt(bytes, bytes2);
    }

    public static string Sm4Encrypt(byte[] sourceData, byte[] keyBytes) {
      KeyParameter parameters = ParameterUtilities.CreateKeyParameter("SM4", keyBytes);
      IBufferedCipher cipher = CipherUtilities.GetCipher("SM4/ECB/PKCS5Padding");
      cipher.Init(true, parameters);
      return Convert.ToBase64String(cipher.DoFinal(sourceData));
    }

    public static string Sm4Decrypt(string base64Str, string sm4Key) {
      byte[] sourceData = Convert.FromBase64String(base64Str);
      byte[] bytes = Encoding.UTF8.GetBytes(sm4Key);
      return Sm4Decrypt(sourceData, bytes);
    }

    public static string Sm4Decrypt(byte[] sourceData, byte[] keyBytes) {
      KeyParameter parameters = ParameterUtilities.CreateKeyParameter("SM4", keyBytes);
      IBufferedCipher cipher = CipherUtilities.GetCipher("SM4/ECB/PKCS5Padding");
      cipher.Init(false, parameters);
      byte[] bytes = cipher.DoFinal(sourceData);
      return Encoding.UTF8.GetString(bytes);
    }

    public static byte[] Decode(string key) {
      if (!Regex.IsMatch(key, "^[0-9a-f]+$", RegexOptions.IgnoreCase)) {
        return Convert.FromBase64String(key);
      }

      return Hex.Decode(key);
    }

    public static string HexString(byte[] bytes) {
      return Hex.ToHexString(bytes);
    }

    private static string GetHash(string text, string key) {
      byte[] bytes = Encoding.UTF8.GetBytes(text + key);
      SHA256 sHA = SHA256.Create();
      sHA.ComputeHash(bytes);
      byte[] hash = sHA.Hash;
      sHA.Clear();
      return BitConverter.ToString(hash).Replace("-", "").ToLower();
    }

    public static string Base64Encode(string content) {
      return Convert.ToBase64String(Encoding.UTF8.GetBytes(content));
    }

    public static string Base64TryDecode(string content) {
      try {
        byte[] bytes = Convert.FromBase64String(content);
        return Encoding.Default.GetString(bytes);
      } catch (Exception) {
        return content;
      }
    }
  }
}
